#include <iostream>
#include <ctime>
#include <unistd.h>
#include <string>
#include "RingQueue.hpp"
#include "Task.hpp"

struct ThreadData
{
    // RingQueue<int>* rq;
    RingQueue<Task>* rq;
    std::string threadname;
};

void *consumer(void *args)
{
    // RingQueue<int> *rq = static_cast<RingQueue<int> *>(args);
    ThreadData *td = static_cast<ThreadData *>(args);
    RingQueue<Task>* rq = td->rq;
    // RingQueue<int>* rq = td->rq;
    std::string name = td->threadname;
    while (true)
    {
        // 消费数据
        // int data = 0;
        // rq->pop(&data);
        // std::cout << "Consumer get data, data is: " << data << ", who: " << name << std::endl;

        Task t;
        rq->pop(&t);
        sleep(1);

        // 处理数据
        t();
        std::cout << "Consumer get task task is : " <<  t.GetTask() << ", who: " << name << ", result: " << t.GetResult() << std::endl;
    }
    return nullptr;
}

void *productor(void *args)
{
    int len = opers.size();
    // sleep(3);
    // RingQueue<int> *rq = static_cast<RingQueue<int> *>(args);
    ThreadData *td = static_cast<ThreadData *>(args);
    // RingQueue<int>* rq = td->rq;
    RingQueue<Task>* rq = td->rq;
    std::string name = td->threadname;
    while (true)
    {
        // 获取数据
        // int data = rand() % 10 + 1;
        int data1 = rand() % 10 + 1;
        usleep(10);
        char op = opers[rand() % len];
        int data2 = rand() % 10 + 1;

        Task t(data1, data2, op);


        // 生产数据
        // rq->push(data);
        rq->push(t);

        // std::cout << "Productor data done, data is: " << data << ", who: " << name << std::endl;
        std::cout << "Productor task done, task is : " << t.GetTask() << ", who: " << name << ", result: " << t.GetResult() << std::endl;
        // sleep(1);
    }
    return nullptr;
}

int main()
{
    srand(time(nullptr));
    // RingQueue<int> *rq = new RingQueue<int>(10);
    RingQueue<Task> *rq = new RingQueue<Task>();
    pthread_t c[3], p[5];

    for (int i = 0; i < 1; ++i)
    {
        ThreadData* td = new ThreadData();
        td->rq = rq;
        td->threadname = "consumer-" + std::to_string(i);
        // pthread_create(c + i, nullptr, consumer, rq);
        pthread_create(c + i, nullptr, consumer, td);
    }

    for (int i = 0; i < 1; ++i)
    {
        ThreadData* td = new ThreadData();
        td->rq = rq;
        td->threadname = "productor-" + std::to_string(i);
        // pthread_create(p + i, nullptr, productor, rq);
        pthread_create(p + i, nullptr, productor, td);
    }

    for (int i = 0; i < 1; ++i)
    {
        pthread_join(c[i], nullptr);
    }

    for (int i = 0; i < 1; ++i)
    {
        pthread_join(p[i], nullptr);
    }
    return 0;
}